#include "AsynchronousSramController1.h" // IWYU pragma: keep

void bsp::AsynchronousSramController1::Initialize(base::asynchronous_sram::asynchronous_sram_timing const &timing)
{
	__HAL_RCC_FSMC_CLK_ENABLE();

	// Perform the SRAM1 memory initialization sequence
	_sram_handle.Instance = FSMC_NORSRAM_DEVICE;
	_sram_handle.Extended = FSMC_NORSRAM_EXTENDED_DEVICE;

	// _sram_handle.Init
	_sram_handle.Init.NSBank = FSMC_NORSRAM_BANK1;
	_sram_handle.Init.DataAddressMux = FSMC_DATA_ADDRESS_MUX_DISABLE;
	_sram_handle.Init.MemoryType = FSMC_MEMORY_TYPE_SRAM;
	_sram_handle.Init.MemoryDataWidth = FSMC_NORSRAM_MEM_BUS_WIDTH_16;
	_sram_handle.Init.BurstAccessMode = FSMC_BURST_ACCESS_MODE_DISABLE;
	_sram_handle.Init.WaitSignalPolarity = FSMC_WAIT_SIGNAL_POLARITY_LOW;
	_sram_handle.Init.WrapMode = FSMC_WRAP_MODE_DISABLE;
	_sram_handle.Init.WaitSignalActive = FSMC_WAIT_TIMING_BEFORE_WS;
	_sram_handle.Init.WriteOperation = FSMC_WRITE_OPERATION_ENABLE;
	_sram_handle.Init.WaitSignal = FSMC_WAIT_SIGNAL_DISABLE;
	_sram_handle.Init.ExtendedMode = FSMC_EXTENDED_MODE_DISABLE;

	// 使能异步等待信号。
	//
	// XHIF 有互斥机制，避免 ERTEC200P 和 XHIF 主机同时访问同一块内存区域，如果 STM32
	// 发起读写时 ERTEC200P 正在读写，会让 STM32 等待。
	_sram_handle.Init.AsynchronousWait = FSMC_ASYNCHRONOUS_WAIT_ENABLE;

	_sram_handle.Init.WriteBurst = FSMC_WRITE_BURST_DISABLE;
	_sram_handle.Init.PageSize = FSMC_PAGE_SIZE_NONE;

	/* Timing */
	FSMC_NORSRAM_TimingTypeDef Timing{};
	Timing.AddressSetupTime = timing.address_setup_clock_cycle_count();
	Timing.AddressHoldTime = timing.address_hold_clock_cycle_count();
	Timing.DataSetupTime = timing.data_setup_clock_cycle_count();
	Timing.BusTurnAroundDuration = timing.bus_turn_around_clock_cycle_count();
	Timing.AccessMode = FSMC_ACCESS_MODE_A;

	if (HAL_SRAM_Init(&_sram_handle, &Timing, nullptr) != HAL_OK)
	{
		throw std::runtime_error{"初始化失败"};
	}
}
